/**
  ******************************************************************************
  * @file    main.c
  * @author  MCD Application Team
  * @version V1.1.0
  * @date    31-July-2013
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "stm32f4x7_eth.h"
#include "netconf.h"
#include "main.h"
#include "lwip/tcpip.h"
#include "httpserver-socket.h"
#include "serial_debug.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/*--------------- LCD Messages ---------------*/
#if defined(STM32F40XX)
    #define MESSAGE1 "    STM32F40/41x     "
#elif defined(STM32F427X)
    #define MESSAGE1 "     STM32F427x      "
#endif
#define MESSAGE2 "  STM32F-4 Series   "
#define MESSAGE3 "Basic WebServer Demo"
#define MESSAGE4 "                    "

/*--------------- Tasks Priority -------------*/
#define MAIN_TASK_PRIO (tskIDLE_PRIORITY + 1)
#define DHCP_TASK_PRIO (tskIDLE_PRIORITY + 4)
#define LED_TASK_PRIO (tskIDLE_PRIORITY + 2)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void LCD_LED_Init(void);
void ToggleLed1(void* pvParameters);
void ToggleLed2(void* pvParameters);
void ToggleLed4(void* pvParameters);
void Main_task(void* pvParameters);
int mqtt_client(void);
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
    /*!< At this stage the microcontroller clock setting is already configured to
       168 MHz, this is done through SystemInit() function which is called from
       startup file (startup_stm32f4xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f4xx.c file
     */

    /* Configures the priority grouping: 4 bits pre-emption priority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

    /* Init task */
    xTaskCreate(Main_task, "Main", configMINIMAL_STACK_SIZE * 2, NULL, MAIN_TASK_PRIO, NULL);

    /* Start scheduler */
    vTaskStartScheduler();

    /* We should never get here as control is now taken by the scheduler */
    for (;;)
        ;
}
/**
  * @brief  Toggle Led4 task
  * @param  pvParameters not used
  * @retval None
  */
void iot_task(void* pvParameters)
{
    extern __IO uint8_t DHCP_state;
    for (;;)
    {
        if (DHCP_state == DHCP_ADDRESS_ASSIGNED)
        {
            mqtt_client();
        }
        vTaskDelay(1000);
    }
}

void Main_task(void* pvParameters)
{
#ifdef SERIAL_DEBUG
    DebugComPort_Init();
    printf("start...\r\n");
    printf("FreeRTOS %s\r\n", tskKERNEL_VERSION_NUMBER);
#endif


    /*Initialize LCD and Leds */
    LCD_LED_Init();
    BEEP_Init();

    rtc_init1();
    /* configure ethernet (GPIOs, clocks, MAC, DMA) */
    ETH_BSP_Config();

    /* Initilaize the LwIP stack */
    LwIP_Init();
#if 0
    /* Initialize webserver demo */
    http_server_socket_init();
#endif
#ifdef USE_DHCP
    /* Start DHCPClient */
    xTaskCreate(LwIP_DHCP_task, "DHCP", configMINIMAL_STACK_SIZE * 2, NULL, DHCP_TASK_PRIO, NULL);
#endif
    /* Start toogleLed4 task : Toggle LED4  every 250ms */
    xTaskCreate(ToggleLed4, "LED4", configMINIMAL_STACK_SIZE, NULL, LED_TASK_PRIO, NULL);

    /* Start toogleLed4 task : Toggle LED2  every 250ms */
    xTaskCreate(ToggleLed2, "LED2", configMINIMAL_STACK_SIZE, NULL, LED_TASK_PRIO, NULL);

    /* Start toogleLed1 task : Toggle LED1  every 250ms */
    xTaskCreate(ToggleLed1, "LED1", configMINIMAL_STACK_SIZE, NULL, LED_TASK_PRIO, NULL);

    /* Start iot task  */
#ifdef DATA_IN_ExtSRAM
    xTaskCreate(iot_task, "IOT", configMINIMAL_STACK_SIZE * 8 * 8, NULL, LED_TASK_PRIO, NULL);
#else
    xTaskCreate(iot_task, "IOT", configMINIMAL_STACK_SIZE * 20, NULL, LED_TASK_PRIO, NULL);
#endif
    for (;;)
    {
        vTaskDelete(NULL);
    }
}

/**
  * @brief  Toggle Led4 task
  * @param  pvParameters not used
  * @retval None
  */
void ToggleLed4(void* pvParameters)
{
    for (;;)
    {
        /* toggle LED4 each 250ms */
        if (DHCP_state == DHCP_ADDRESS_ASSIGNED)
        {
            STM_EVAL_LEDOn(LED4);
        }
        vTaskDelay(100);
        STM_EVAL_LEDOff(LED4);
        vTaskDelay(2000);
    }
}

/**
  * @brief  Toggle Led1 task
  * @param  pvParameters not used
  * @retval None
  */
void ToggleLed2(void* pvParameters)
{
    for (;;)
    {
        if (DHCP_state == DHCP_WAIT_ADDRESS)
        {
            STM_EVAL_LEDOn(LED2);
        }
        vTaskDelay(100);
        STM_EVAL_LEDToggle(LED2);
        vTaskDelay(1000);
    }
}

/**
  * @brief  Toggle Led1 task
  * @param  pvParameters not used
  * @retval None
  */
void ToggleLed1(void* pvParameters)
{
    for (;;)
    {

        if (DHCP_state == DHCP_START)
        {
            STM_EVAL_LEDOn(LED1);
        }
        vTaskDelay(100);
        STM_EVAL_LEDOff(LED1);
        vTaskDelay(500);
    }
}

/**
  * @brief  Initializes the LCD and LEDs resources.
  * @param  None
  * @retval None
  */
void LCD_LED_Init(void)
{
#ifdef USE_LCD
    /* Initialize the STM324xG-EVAL's LCD */
    STM324xG_LCD_Init();
#endif

    /* Initialize STM324xG-EVAL's LEDs */
    STM_EVAL_LEDInit(LED1);
    STM_EVAL_LEDInit(LED2);
    STM_EVAL_LEDInit(LED4);

#ifdef USE_LCD
    /* Clear the LCD */
    LCD_Clear(Black);

    /* Set the LCD Back Color */
    LCD_SetBackColor(Black);

    /* Set the LCD Text Color */
    LCD_SetTextColor(White);

    /* Display message on the LCD*/
    LCD_DisplayStringLine(Line0, (uint8_t*)MESSAGE1);
    LCD_DisplayStringLine(Line1, (uint8_t*)MESSAGE2);
    LCD_DisplayStringLine(Line2, (uint8_t*)MESSAGE3);
    LCD_DisplayStringLine(Line3, (uint8_t*)MESSAGE4);
#endif
}

/**
  * @brief  Inserts a delay time.
  * @param  nCount: number of Ticks to delay.
  * @retval None
  */
void Delay(uint32_t nCount)
{
    vTaskDelay(nCount);
}

#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}
#endif
/*-----------------------------------------------------------*/

void vApplicationMallocFailedHook(void)
{
    /* vApplicationMallocFailedHook() will only be called if
    configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
    function that will get called if a call to pvPortMalloc() fails.
    pvPortMalloc() is called internally by the kernel whenever a task, queue,
    timer or semaphore is created.  It is also called by various parts of the
    demo application.  If heap_1.c or heap_2.c are used, then the size of the
    heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
    FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
    to query the size of free heap space that remains (although it does not
    provide information on how the remaining heap might be fragmented). */
    printf("error\r\n");
    printf("pvPortMalloc\r\n");
    taskDISABLE_INTERRUPTS();
    for (;;);
}
/*-----------------------------------------------------------*/

void vApplicationIdleHook(void)
{
    /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
    to 1 in FreeRTOSConfig.h.  It will be called on each iteration of the idle
    task.  It is essential that code added to this hook function never attempts
    to block in any way (for example, call xQueueReceive() with a block time
    specified, or call vTaskDelay()).  If the application makes use of the
    vTaskDelete() API function (as this demo application does) then it is also
    important that vApplicationIdleHook() is permitted to return to its calling
    function, because it is the responsibility of the idle task to clean up
    memory allocated by the kernel to any task that has since been deleted. */
    __WFI();
}
/*-----------------------------------------------------------*/

void vApplicationStackOverflowHook(TaskHandle_t pxTask, char* pcTaskName)
{
    (void) pcTaskName;
    (void) pxTask;
    printf("error\r\n");
    printf("task:%s StackOverflow\r\n", pcTaskName);

    /* Run time stack overflow checking is performed if
    configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
    function is called if a stack overflow is detected. */
    taskDISABLE_INTERRUPTS();
    for (;;);
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
